
package com.amkai.aes.webservice.binary.objecthandler;

/**
 * @author CyB
 */
import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;

import com.amkai.aes.aescommon.AESSettings;
import com.amkai.aes.aescommon.dictionary.SharedDictionaryManagerCommon;
import com.amkai.aes.aescommon.dictionary.SharedKind;
import com.amkai.aes.aescommon.service.binary.job.PhysStaffJob;
import com.amkai.aes.aescommon.service.result.PhysStaffListResult;
import com.amkai.aes.generatedbeans.binarymgr.BinaryData;
import com.amkai.aes.generatedbeans.common.Address;
import com.amkai.aes.generatedbeans.dictionary.ItemKind;
import com.amkai.aes.generatedbeans.digitaldocumentmgr.BinaryContent;
import com.amkai.aes.generatedbeans.digitaldocumentmgr.Document;
import com.amkai.aes.generatedbeans.digitaldocumentmgr.ImageContent;
import com.amkai.aes.generatedbeans.digitaldocumentmgr.Page;
import com.amkai.aes.generatedbeans.digitaldocumentmgr.PageContent;
import com.amkai.aes.generatedbeans.passport.Passport;
import com.amkai.aes.generatedbeans.personnel.PersonnelInfo;
import com.amkai.aes.generatedbeans.personnel.details.Certification;
import com.amkai.aes.generatedbeans.personnel.details.Education;
import com.amkai.aes.generatedbeans.personnel.details.EmploymentInformation;
import com.amkai.aes.generatedbeans.personnel.details.Indicator;
import com.amkai.aes.generatedbeans.personnel.details.License;
import com.amkai.aes.generatedbeans.personnel.details.OccurenceInformation;
import com.amkai.aes.generatedbeans.personnel.details.PhysStaffInsurancePolicy;
import com.amkai.aes.generatedbeans.personnel.details.ReviewInformation;
import com.amkai.aes.generatedbeans.personnel.details.SanctionInformation;
import com.amkai.aes.generatedbeans.physstaff.CarrierRelatedPhysStaffFacilityId;
import com.amkai.aes.generatedbeans.physstaff.CarrierRelatedPhysStaffIds;
import com.amkai.aes.generatedbeans.physstaff.PhysStaff;
import com.amkai.aes.generatedbeans.physstaff.Physician;
import com.amkai.aes.generatedbeans.physstaff.Staff;
import com.amkai.aes.generatedbeans.rcm.RCMCollector;
import com.amkai.aes.generatedbeans.rcm.RCMFUOption;
import com.amkai.aes.generatedbeans.rcm.RCMItemOption;
import com.amkai.aes.generatedbeans.registration.EmergencyContact;
import com.amkai.aes.generatedbeans.registration.Person;
import com.amkai.aes.server.dictionary.DictionarySchedulingResourceManager;
import com.amkai.aes.server.manager.personnel.PersonnelManager;
import com.amkai.aes.server.util.AesServerUtils;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

public class PhysStaffListHandler implements JobObjectHandler<PhysStaffJob, java.io.Serializable, PhysStaffListResult> {
	private static final Log log = LogFactory.getLog(PhysStaffListHandler.class);

	// KKORNEL: AES-6494
	private static String QUERY_STRING = "SELECT staff FROM PhysStaff staff" + " LEFT JOIN FETCH staff.person" + 
	                                     " LEFT JOIN FETCH staff.physStaffSpecialtyAssociations pssa" + " LEFT JOIN FETCH pssa.specialty";

	// KKORNEL: AES-7355
	private static String FETCH_STRING_FOR_PARTIALLY_SHARED_ITEMS = " LEFT JOIN FETCH staff.itemGroup ig LEFT JOIN FETCH ig.itemStateCodes isc LEFT JOIN FETCH isc.state";
	private static String FETCH_STRING_FOR_NON_PARTIALLY_SHARED_ITEMS = " LEFT JOIN FETCH staff.itemStateCodes isc LEFT JOIN FETCH isc.state";

	private static String WHERE_QUERY_STRING = " WHERE staff.id = :id";

	private static String FETCHED_QUERY_STRING_END = " LEFT JOIN FETCH staff.carrierRelatedPhysStaffFacilityIds" + " LEFT JOIN FETCH staff.carrierRelatedPhysStaffIdses" + " LEFT JOIN FETCH staff.person.maritalStatus" + " LEFT JOIN FETCH staff.person.addresses" + " LEFT JOIN FETCH staff.personnelInfo" + " LEFT JOIN FETCH staff.personnelInfo.personnelCommon" + " LEFT JOIN FETCH staff.personnelInfo.personnelCommon.spouse" + " LEFT JOIN FETCH staff.personnelInfo.privilege" + " LEFT JOIN FETCH staff.specialty" + PhysStaffListHandler.WHERE_QUERY_STRING;

	private static String FIX_ITEM_LOADER_FETCHED_QUERY_STRING_END = " LEFT JOIN FETCH staff.person.maritalStatus" + " LEFT JOIN FETCH staff.person.addresses" + " LEFT JOIN FETCH staff.personnelInfo" + " LEFT JOIN FETCH staff.personnelInfo.personnelCommon" + " LEFT JOIN FETCH staff.personnelInfo.personnelCommon.spouse" + " LEFT JOIN FETCH staff.personnelInfo.privilege" + " LEFT JOIN FETCH staff.specialty" + PhysStaffListHandler.WHERE_QUERY_STRING;

	private void loadAccreditations(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null && personnelInfo.getAccreditation() != null) {
			personnelInfo.getAccreditation().getId();
			for (Indicator indicator : personnelInfo.getAccreditation().getIndicators()) {
				indicator.getId();
				if (indicator.getKind() != null) {
					indicator.getKind().getName();
				}
			}
			for (License license : personnelInfo.getAccreditation().getLicenses()) {
				license.getId();
				if (license.getKind() != null) {
					license.getKind().getName();
				}
			}
			for (Certification certification : personnelInfo.getAccreditation().getCertifications()) {
				certification.getId();
				if (certification.getKind() != null) {
					certification.getKind().getName();
				}
				if (certification.getCertifyingBoard() != null) {
					certification.getCertifyingBoard().getName();
				}
			}
		}
	}

	private void loadAddress(final PhysStaff physStaff) {
		if (physStaff != null) {
			for (Address address : physStaff.getPerson().getAddresses()) {
				address.getLocation().getId();
				if (address.getLocation().getPhone() != null) {
					address.getLocation().getPhone().getNumber();
				}
				if (address.getLocation().getFax() != null) {
					address.getLocation().getFax().getNumber();
				}
				if (address.getLocation().getAlterPhone() != null) {
					address.getLocation().getAlterPhone().getNumber();
				}
				if (address.getLocation().getZipCode() != null) {
					if (address.getLocation().getZipCode().getCity() != null) {
						address.getLocation().getZipCode().getCity().getName();
					}
					if (address.getLocation().getZipCode().getZip() != null) {
						address.getLocation().getZipCode().getZip().getName();

						if (address.getLocation().getZipCode().getZip().getState() != null) {
							address.getLocation().getZipCode().getZip().getState().getName();
						}
					}
				}
			}
		}
	}

	private void loadCarrierRelatedIds(final PhysStaff physStaff) {
		if (physStaff != null && physStaff.getCarrierRelatedPhysStaffIdses() != null) {
			for (CarrierRelatedPhysStaffIds staffId : physStaff.getCarrierRelatedPhysStaffIdses()) {
				staffId.getId();
			}

			for (CarrierRelatedPhysStaffFacilityId facilityStaffId : physStaff.getCarrierRelatedPhysStaffFacilityIds()) {
				facilityStaffId.getId();
			}
		}
	}

	private void loadCredentialing(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null && personnelInfo.getCredentialing() != null) {
			personnelInfo.getCredentialing().getId();
			if (personnelInfo.getCredentialing().getCredentialingStatus() != null) {
				personnelInfo.getCredentialing().getCredentialingStatus().getName();
			}
			for (PhysStaffInsurancePolicy policy : personnelInfo.getCredentialing().getPhysStaffInsurancePolicies()) {
				policy.getId();
				if (policy.getInsuranceCarrier() != null) {
					policy.getInsuranceCarrier().getName();
				}
				if (policy.getInsurancePlanType() != null) {
					policy.getInsurancePlanType().getName();
				}
			}
		}
	}

	private void loadEducations(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null) {
			for (Education education : personnelInfo.getEducations()) {
				education.getId();
			}
		}
	}

	private void loadEmergencyContact(final Person person) throws Exception {
		if (person != null && person.getPersonnelCommon() != null) {
			EmergencyContact emergencyContact = person.getPersonnelCommon().getEmergencyContact();
			if (emergencyContact != null) {
				emergencyContact.getId();
				if (emergencyContact.getPerson() != null) {
					emergencyContact.getPerson().getId();
					emergencyContact.getPerson().getDisplayName();
					if (emergencyContact.getPerson().getAlternatePhone() != null) {
						emergencyContact.getPerson().getAlternatePhone().getNumber();
					}
				}
				if (emergencyContact.getPhone() != null) {
					emergencyContact.getPhone().getNumber();
				}
				if (emergencyContact.getRelationshipEntry() != null) {
					emergencyContact.getRelationshipEntry().getA();
					emergencyContact.getRelationshipEntry().getB();
					emergencyContact.getRelationshipEntry().getRelationship().getName();
					emergencyContact.getRelationshipEntry().getRelationshipEntryKind();
				}
			}
		}
	}

	private void loadEmployment(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null) {
			for (EmploymentInformation employment : personnelInfo.getEmploymentInformations()) {
				employment.getId();
				if (employment.getStatus() != null) {
					employment.getStatus().getName();
				}
			}
		}
	}

	private void loadOccurrences(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null) {
			for (OccurenceInformation occurrence : personnelInfo.getOccurenceInformations()) {
				occurrence.getId();
				if (occurrence.getReportedBy() != null) {
					occurrence.getReportedBy().getDisplayName();
				}
				if (occurrence.getOccurenceType() != null) {
					occurrence.getOccurenceType().getName();
				}
				if( occurrence.getLevelOfHarm() != null) {
					occurrence.getLevelOfHarm().getName();
				}
			}
		}
	}

	private void loadImageDocument(SessionManager sessionManager, final PhysStaff physStaff) throws Exception {
		//AES-4083
		if (physStaff.getPerson().getPersonnelCommon() != null && physStaff.getPerson().getPersonnelCommon().getPicture() != null) {
			Document picture = physStaff.getPerson().getPersonnelCommon().getPicture();
			picture.getName();
			for(Page p : picture.getPages()) {
				BinaryData bd = null;
				p.getCreationTime();
				p.getName();
				PageContent pc = p.getPageContent();
				switch(pc.getContentKind()) {
				case BINARY :
					BinaryContent bc = sessionManager.get(BinaryContent.class, pc.getId());
					bd = bc.getBinaryData();
					bd.getOriginalName();
					bd.getStoreName();
					break;
				case IMAGE :
					ImageContent ic = sessionManager.get(ImageContent.class, pc.getId());
					bd = ic.getBinaryData();
					if(bd != null) {
						bd.getOriginalName();
						bd.getStoreName();
					}
					break;
				}
			}
		}
		//--
	}
	
	// AES-4230
	private void loadPerson(final PhysStaff physStaff) {
		if (physStaff != null && physStaff.getPerson() != null) {
			physStaff.getPerson().getDisplayName();
			if (physStaff.getPerson().getPersonnelCommon() != null) {
				if (physStaff.getPerson().getPersonnelCommon().getSpouse() != null) {
					physStaff.getPerson().getPersonnelCommon().getSpouse().getDisplayName();
				}
			}
		}
	}

	// --

	private void loadPhysicianSpecificProperties(final PhysStaff physStaff) {
		if (physStaff instanceof Physician) {
			Physician phys = (Physician) physStaff; 
			RCMItemOption rio = phys.getRcmItemOption();
			if(rio != null) {
				RCMFUOption fu = rio.getRcmFUOption();
				RCMCollector col = rio.getRcmCollector();
				if(fu != null) fu.getInitialFUD();
				if(col != null) {
					col.getDisplayString();
				}
			}
			// KKORNEL: AES-8082
			if (phys.getRole() != null) {
				phys.getRole().getName();
			}
		}
	}

	private void loadReviews(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null) {
			for (ReviewInformation review : personnelInfo.getReviewInformations()) {
				review.getId();
				if (review.getPerformedBy() != null) {
					review.getPerformedBy().getPerson().getDisplayName();
				}
			}
		}
	}

	private void loadSanctions(final PersonnelInfo personnelInfo) {
		if (personnelInfo != null) {
			for (SanctionInformation sanction : personnelInfo.getSanctionInformations()) {
				sanction.getId();
				if (sanction.getType() != null) {
					sanction.getType().getName();
				}
			}
		}
	}

	private void loadSchedulingResource(final SessionManager manager, final PhysStaff physStaff) throws Exception {
		DictionarySchedulingResourceManager dsrm = new DictionarySchedulingResourceManager(manager);
		physStaff.setTransientSchedulingResource(dsrm.isActiveSchedulingResource(physStaff));
	}

	private void loadStaffSpecificProperties(final PhysStaff physStaff) {
		if (physStaff instanceof Staff) {
			if (((Staff) physStaff).getStaffRole() != null) {
				((Staff) physStaff).getStaffRole().getName();
			}
		}
	}

	@Override
	public PhysStaffListResult process(final PhysStaffJob job, final Serializable object) throws Exception {
		PhysStaffListResult result = new PhysStaffListResult();

		SessionManager manager = SiteManager.Start();
		manager.openSession();
		try {
			Query query = null;

			// KKORNEL: AES-14980
			if (job.getId() != null) {
//			if (job.getId() == null) {
//				query = manager.execute(PhysStaffListHandler.QUERY_STRING);
//				List<PhysStaff> items = query.list();
//				result.setPhysStaffList(items);
//			} else {
				PhysStaffListHandler.log.debug("Loading PhysStaff...");
				ItemKind itemKind = ItemKind.valueOf(manager.execute("SELECT kindWrapper.name FROM Item WHERE id = :id").setLong("id", job.getId().longValue()).uniqueResult().toString());

				// KKORNEL: AES-7355
				if (SharedDictionaryManagerCommon.getInstance().canHaveStateCodes(itemKind)) {
					if (SharedDictionaryManagerCommon.getInstance().getSharedKind(itemKind) == SharedKind.PARTIALLY_SHARED) {
						// KKORNEL: AES-6041
						if (AESSettings.FIX_DICTIONARY_ITEM_LOADER) {
							query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCH_STRING_FOR_PARTIALLY_SHARED_ITEMS+PhysStaffListHandler.FIX_ITEM_LOADER_FETCHED_QUERY_STRING_END);					
						} else {
							query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCH_STRING_FOR_PARTIALLY_SHARED_ITEMS+PhysStaffListHandler.FETCHED_QUERY_STRING_END);
						}
					} else {
						// KKORNEL: AES-6041
						if (AESSettings.FIX_DICTIONARY_ITEM_LOADER) {
							query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCH_STRING_FOR_NON_PARTIALLY_SHARED_ITEMS+PhysStaffListHandler.FIX_ITEM_LOADER_FETCHED_QUERY_STRING_END);					
						} else {
							query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCH_STRING_FOR_NON_PARTIALLY_SHARED_ITEMS+PhysStaffListHandler.FETCHED_QUERY_STRING_END);
						}
					}
					
				} else {
					// KKORNEL: AES-6041
					if (AESSettings.FIX_DICTIONARY_ITEM_LOADER) {
						query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FIX_ITEM_LOADER_FETCHED_QUERY_STRING_END);					
					} else {
						query = manager.execute(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCHED_QUERY_STRING_END);
					}
				}
				query.setParameter("id", job.getId());

				PhysStaff physStaff = (PhysStaff) query.uniqueResult();
				if (physStaff.getPersonnelInfo() == null) {
					manager.openTransaction();
					try {
						PhysStaffListHandler.log.debug("Personnel info is NULL! Creating...");
						// KKORNEL: AES-14980
						PersonnelManager.createAndSavePersonnelInfo(manager, physStaff);
//						PersonnelInfo personnelInfo = RADBeanFactory.getInstance().createBean(PersonnelInfo.class);
//						physStaff.setPersonnelInfo(personnelInfo);
//
//						manager.saveRAD(personnelInfo.getAccreditation());
//						manager.saveRAD(personnelInfo.getCredentialing());
//						manager.saveRAD(personnelInfo.getPrivilege());
//						manager.saveRAD(personnelInfo);
//						manager.saveRAD(physStaff);

						manager.commitTransaction();
					} catch (Exception exception) {
						manager.rollbackTransaction();
						PhysStaffListHandler.log.error("", exception);
						throw exception;
					}
					PhysStaffListHandler.log.debug("Personnel info saved! Reloading physStaff...");

					query = manager.execute(String.format(PhysStaffListHandler.QUERY_STRING+PhysStaffListHandler.FETCHED_QUERY_STRING_END, new Object[] { ":id" }));
					query.setParameter("id", job.getId());
					physStaff = (PhysStaff) query.uniqueResult();
				}

				PhysStaffListHandler.log.debug("Initializing PhysStaff...");
				// KKORNEL: AES-4465
				// staff.setTranzientActive(dm.isActive(staff,
				// job.getModuleDepartment()));

				// AES-4230
				loadPerson(physStaff);
				// --
				loadAddress(physStaff);
				loadAccreditations(physStaff.getPersonnelInfo());
				loadCredentialing(physStaff.getPersonnelInfo());
				loadEducations(physStaff.getPersonnelInfo());
				loadEmergencyContact(physStaff.getPerson());
				loadEmployment(physStaff.getPersonnelInfo());
				loadOccurrences(physStaff.getPersonnelInfo());
				loadReviews(physStaff.getPersonnelInfo());
				loadSanctions(physStaff.getPersonnelInfo());

				loadCarrierRelatedIds(physStaff);

				loadSchedulingResource(manager, physStaff);

				loadStaffSpecificProperties(physStaff);
				loadPhysicianSpecificProperties(physStaff);
				
				loadImageDocument(manager, physStaff);
				loadSupervisor(physStaff);
				
				AesServerUtils.loadLicenseKindAssociations(physStaff);

				result.setPhysStaff(physStaff);
			}
		} finally {
			manager.closeSession();
		}
		return result;
	}

	private void loadSupervisor(PhysStaff physStaff) {
		Passport p = physStaff.getSupervisor();
		if(p != null) {
			p.getName();
			p.getId();
		}
	}
}
